"""
访问者模式基础类

定义访问者模式的抽象接口和基础实现。
"""

from abc import ABC, abstractmethod
from typing import Any, Dict, List, Optional, Type, TypeVar

# 前向声明，避免循环导入
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from ..ast.base import Ast, AstContext
    from ..ast.nodes import *

T = TypeVar('T')


class Visitor(ABC):
    """
    通用访问者接口
    
    定义访问者模式的基本接口，所有访问者都应该实现此接口。
    """
    
    @abstractmethod
    def visit(self, ast: 'Ast', ctx: Any) -> Any:
        """访问AST节点"""
        pass


class AstVisitor(Visitor):
    """
    AST访问者抽象基类
    
    为AST节点提供访问者模式的具体实现框架。
    """
    
    def visit(self, ast: 'Ast', context: 'AstContext') -> Any:
        """
        访问AST节点的入口方法
        
        根据节点类型分发到对应的访问方法。
        """
        # 更新上下文中的当前节点
        context.current_node = ast
        
        # 根据节点类型分发
        method_name = f"visit_{ast.node_type.value}"
        method = getattr(self, method_name, self.visit_default)
        
        try:
            return method(ast, context)
        except Exception as e:
            # 记录错误信息到上下文
            context.error_info = {
                "node_id": ast.node_id,
                "node_type": ast.node_type.value,
                "error": str(e),
                "error_type": type(e).__name__
            }
            raise
    
    def visit_default(self, ast: 'Ast', context: 'AstContext') -> Any:
        """默认访问方法，处理未知节点类型"""
        raise NotImplementedError(f"未实现对节点类型 {ast.node_type} 的访问方法")
    
    # ========================================================================
    # 基础控制节点访问方法
    # ========================================================================
    
    def visit_sequence(self, ast: 'Sequence', context: 'AstContext') -> Any:
        """访问顺序执行节点"""
        raise NotImplementedError("子类必须实现 visit_sequence 方法")
    
    def visit_parallel(self, ast: 'Parallel', context: 'AstContext') -> Any:
        """访问并行执行节点"""
        raise NotImplementedError("子类必须实现 visit_parallel 方法")
    
    def visit_conditional(self, ast: 'Conditional', context: 'AstContext') -> Any:
        """访问条件执行节点"""
        raise NotImplementedError("子类必须实现 visit_conditional 方法")
    
    def visit_loop(self, ast: 'Loop', context: 'AstContext') -> Any:
        """访问循环执行节点"""
        raise NotImplementedError("子类必须实现 visit_loop 方法")
    
    # ========================================================================
    # 视频处理节点访问方法
    # ========================================================================
    
    def visit_ffmpeg_slice(self, ast: 'FfmpegSlice', context: 'AstContext') -> Any:
        """访问FFmpeg切片节点"""
        raise NotImplementedError("子类必须实现 visit_ffmpeg_slice 方法")
    
    def visit_extract_metadata(self, ast: 'ExtractMetadata', context: 'AstContext') -> Any:
        """访问元数据提取节点"""
        raise NotImplementedError("子类必须实现 visit_extract_metadata 方法")
    
    def visit_scan_directory(self, ast: 'ScanDirectory', context: 'AstContext') -> Any:
        """访问目录扫描节点"""
        raise NotImplementedError("子类必须实现 visit_scan_directory 方法")
    
    # ========================================================================
    # AI分类节点访问方法
    # ========================================================================
    
    def visit_gemini_classify(self, ast: 'GeminiClassify', context: 'AstContext') -> Any:
        """访问Gemini分类节点"""
        raise NotImplementedError("子类必须实现 visit_gemini_classify 方法")
    
    # ========================================================================
    # 输出节点访问方法
    # ========================================================================
    
    def visit_output_draft(self, ast: 'OutputDraft', context: 'AstContext') -> Any:
        """访问输出草稿节点"""
        raise NotImplementedError("子类必须实现 visit_output_draft 方法")
    
    def visit_organize_files(self, ast: 'OrganizeFiles', context: 'AstContext') -> Any:
        """访问文件整理节点"""
        raise NotImplementedError("子类必须实现 visit_organize_files 方法")
    
    def visit_generate_report(self, ast: 'GenerateReport', context: 'AstContext') -> Any:
        """访问报告生成节点"""
        raise NotImplementedError("子类必须实现 visit_generate_report 方法")
    
    # ========================================================================
    # 工具节点访问方法
    # ========================================================================
    
    def visit_file_operation(self, ast: 'FileOperation', context: 'AstContext') -> Any:
        """访问文件操作节点"""
        raise NotImplementedError("子类必须实现 visit_file_operation 方法")
    
    def visit_data_transform(self, ast: 'DataTransform', context: 'AstContext') -> Any:
        """访问数据转换节点"""
        raise NotImplementedError("子类必须实现 visit_data_transform 方法")


class BaseAstVisitor(AstVisitor):
    """
    基础AST访问者实现
    
    提供一些通用的访问者功能实现，子类可以继承并重写特定方法。
    """
    
    def __init__(self):
        self.visited_nodes: List[str] = []
        self.context_stack: List['AstContext'] = []
    
    def visit(self, ast: 'Ast', context: 'AstContext') -> Any:
        """重写visit方法，添加访问跟踪"""
        # 记录访问的节点
        self.visited_nodes.append(ast.node_id)
        
        # 保存上下文栈
        self.context_stack.append(context)
        
        try:
            result = super().visit(ast, context)
            return result
        finally:
            # 恢复上下文栈
            self.context_stack.pop()
    
    def get_current_context(self) -> Optional['AstContext']:
        """获取当前上下文"""
        return self.context_stack[-1] if self.context_stack else None
    
    def get_visited_nodes(self) -> List[str]:
        """获取已访问的节点列表"""
        return self.visited_nodes.copy()
    
    def reset(self) -> None:
        """重置访问状态"""
        self.visited_nodes.clear()
        self.context_stack.clear()
    
    # ========================================================================
    # 默认实现 - 子类可以重写
    # ========================================================================
    
    def visit_sequence(self, ast: 'Sequence', context: 'AstContext') -> Any:
        """顺序执行节点的默认实现"""
        results = []
        for child in ast.children:
            result = self.visit(child, context)
            results.append(result)
        return results
    
    def visit_parallel(self, ast: 'Parallel', context: 'AstContext') -> Any:
        """并行执行节点的默认实现"""
        # 默认实现：顺序执行（子类应该重写为真正的并行执行）
        results = []
        for child in ast.children:
            result = self.visit(child, context)
            results.append(result)
        return results
    
    def visit_conditional(self, ast: 'Conditional', context: 'AstContext') -> Any:
        """条件执行节点的默认实现"""
        # 简单的条件评估（子类应该实现更复杂的条件逻辑）
        condition_result = self._evaluate_condition(ast.condition, context)
        
        if condition_result and ast.true_branch:
            return self.visit(ast.true_branch, context)
        elif not condition_result and ast.false_branch:
            return self.visit(ast.false_branch, context)
        
        return None
    
    def visit_loop(self, ast: 'Loop', context: 'AstContext') -> Any:
        """循环执行节点的默认实现"""
        results = []
        iteration = 0
        
        while True:
            # 检查最大迭代次数
            if ast.max_iterations and iteration >= ast.max_iterations:
                break
            
            # 检查循环条件
            if ast.condition and not self._evaluate_condition(ast.condition, context):
                break
            
            # 执行子节点
            for child in ast.children:
                result = self.visit(child, context)
                results.append(result)
            
            iteration += 1
        
        return results
    
    def _evaluate_condition(self, condition: str, context: 'AstContext') -> bool:
        """
        评估条件表达式
        
        这是一个简化的实现，子类应该实现更完整的条件评估逻辑。
        """
        if not condition:
            return True
        
        # 简单的变量检查
        if condition.startswith('$'):
            var_name = condition[1:]
            return bool(context.get_variable(var_name, False))
        
        # 简单的布尔值
        if condition.lower() in ['true', '1', 'yes']:
            return True
        elif condition.lower() in ['false', '0', 'no']:
            return False
        
        # 默认返回True
        return True


class VisitorRegistry:
    """
    访问者注册表
    
    管理不同类型的访问者，支持动态注册和获取。
    """
    
    def __init__(self):
        self._visitors: Dict[str, Type[AstVisitor]] = {}
    
    def register(self, name: str, visitor_class: Type[AstVisitor]) -> None:
        """注册访问者"""
        self._visitors[name] = visitor_class
    
    def get(self, name: str) -> Optional[Type[AstVisitor]]:
        """获取访问者类"""
        return self._visitors.get(name)
    
    def create(self, name: str, *args, **kwargs) -> Optional[AstVisitor]:
        """创建访问者实例"""
        visitor_class = self.get(name)
        if visitor_class:
            return visitor_class(*args, **kwargs)
        return None
    
    def list_visitors(self) -> List[str]:
        """列出所有注册的访问者"""
        return list(self._visitors.keys())
    
    def unregister(self, name: str) -> bool:
        """注销访问者"""
        if name in self._visitors:
            del self._visitors[name]
            return True
        return False


# 全局访问者注册表
visitor_registry = VisitorRegistry()
